using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;
using System;
using Gj.Galaxy.Logic;
using UnityEngine;

namespace Gj.ILRuntimeExt.Adapt
{
    //这个类就是继承适配器类
    public class GameAreaListenerAdaptor : CrossBindingAdaptor
    {
        public override Type BaseCLRType
        {
            get
            {
                //如果你是想一个类实现多个Unity主工程的接口，这里需要return null;
                return typeof(GameAreaListener);//这是你想继承的那个类
//                return null;
            }
        }

        public override Type[] BaseCLRTypes
        {
            get
            {
                //跨域继承只能有1个Adapter，因此应该尽量避免一个类同时实现多个外部接口，
                //ILRuntime虽然支持同时实现多个接口，但是一定要小心这种用法，使用不当很容易造成不可预期的问题
                //日常开发如果需要实现多个DLL外部接口，请在Unity这边先做一个基类实现那些个接口，然后继承那个基类
                //如需一个Adapter实现多个接口，请用下面这行
//                return new Type[] { typeof(BaseUISystem), typeof(UISystem), typeof(GameBeforeListener) };
                return null;
            }
        }

        public override Type AdaptorType
        {
            get
            {
                return typeof(Adaptor);//这是实际的适配器类
            }
        }

        public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
        {
            return new Adaptor(appdomain, instance);//创建一个新的实例
        }

        //实际的适配器类需要继承你想继承的那个类，并且实现CrossBindingAdaptorType接口
        class Adaptor : GameAreaListener, CrossBindingAdaptorType
        {
            ILTypeInstance instance;
            ILRuntime.Runtime.Enviorment.AppDomain appdomain;

            private IMethod mOnEnterArea;
            private bool mOnEnterAreaGot;

            private IMethod mOnProcessArea;
            private bool mOnProcessAreaGot;

            private IMethod mOnDestroy;
            private bool mOnDestroyGot;

            private IMethod mOnSwitchArea;
            private bool mOnSwitchAreaGot;

            private IMethod mOnInstance;
            private bool mOnInstanceGot;
            
            private IMethod mOnConnect;
            private bool mOnConnectGot;
            
            private IMethod mOnFailConnect;
            private bool mOnFailConnectGot;
            
            bool isTestVirtualInvoking = false;
            //缓存这个数组来避免调用时的GC Alloc
            object[] param1 = new object[1];
            object[] param2 = new object[2];
            object[] param7 = new object[7];

            public Adaptor()
            {

            }

            public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
            {
                this.appdomain = appdomain;
                this.instance = instance;
            }

            public ILTypeInstance ILInstance { get { return instance; } }

            public void OnConnect()
            {
                if (!mOnConnectGot)
                {
                    mOnConnect = instance.Type.GetMethod("OnConnect", 0);
                    mOnConnectGot = true;
                }

                if (mOnConnect != null)
                    appdomain.Invoke(mOnConnect, instance);
            }

            public void OnFailConnect()
            {
                if (!mOnFailConnectGot)
                {
                    mOnFailConnect = instance.Type.GetMethod("OnFailConnect", 0);
                    mOnFailConnectGot = true;
                }

                if (mOnFailConnect != null)
                    appdomain.Invoke(mOnFailConnect, instance);
            }

            public void OnSwitchArea()
            {
                if (!mOnSwitchAreaGot)
                {
                    mOnSwitchArea = instance.Type.GetMethod("OnSwitchArea", 0);
                    mOnSwitchAreaGot = true;
                }

                if (mOnSwitchArea != null)
                    appdomain.Invoke(mOnSwitchArea, instance);
            }

            public void OnInstance(int prefabIndex, byte relation, GamePlayer player, Vector3 position, bool isLocal, NetworkEsse master,
                Action<InitSyncListener> cb)
            {
                if (!mOnInstanceGot)
                {
                    mOnInstance = instance.Type.GetMethod("OnInstance", 7);
                    mOnInstanceGot = true;
                }

                param7[0] = prefabIndex;
                param7[1] = relation;
                param7[2] = player;
                param7[3] = position;
                param7[4] = isLocal;
                param7[5] = master;
                param7[6] = cb;
                if (mOnInstance != null)
                    appdomain.Invoke(mOnInstance, instance, param7);
            }

            public void OnDestroy(NetworkEsse esse, GamePlayer player)
            {
                if (!mOnDestroyGot)
                {
                    mOnDestroy = instance.Type.GetMethod("OnDestroy", 2);
                    mOnDestroyGot = true;
                }

                param2[0] = esse;
                param2[1] = player;
                if (mOnDestroy != null)
                    appdomain.Invoke(mOnDestroy, instance, param2);
            }

            public void OnEnterArea(GameAreaType type, Vector3 position)
            {
                if (!mOnEnterAreaGot)
                {
                    mOnEnterArea = instance.Type.GetMethod("OnEnterArea", 2);
                    mOnEnterAreaGot = true;
                }

                param2[0] = type;
                param2[1] = position;
                if (mOnEnterArea != null)
                    appdomain.Invoke(mOnEnterArea, instance, param2);
            }

            public void OnProcessArea(object[] data)
            {
                if (!mOnProcessAreaGot)
                {
                    mOnProcessArea = instance.Type.GetMethod("OnProcessArea", 1);
                    mOnProcessAreaGot = true;
                }

                param1[0] = data;
                if (mOnProcessArea != null)
                    appdomain.Invoke(mOnProcessArea, instance, param1);
            }
        }
    }
}
